module Controller(
    input   [5:0]   opcode,
    input   [5:0]   funct,
    output  [1:0]   RegDst,   
    output  [1:0]   Branch,   
    output  [1:0]   MemtoReg, 
    output          AluSrc,   
    output   [3:0]  AluOp,    
    output          MemWrite, 
    output          RegWrite, 
    output   [1:0]  Jump,     
    output          Sign,
    output   [1:0]  DataType,
    output          DataSign,
    output          MemRead
);

   
    
    //OPCODE
    parameter   RTYPE = 6'b000000;               
    parameter   ADDI  = 6'b001000;               
    parameter   ADDIU = 6'b001001;
    parameter   ANDI  = 6'b001100; 
    parameter   XORI  = 6'b001110;               
    parameter   BEQ   = 6'b000100;    
    parameter   BNE   = 6'b000101;           
    parameter   J     = 6'b000010;               
    parameter   LW    = 6'b100011;               
    parameter   SW    = 6'b101011;
    parameter   LH    = 6'b100001; 
    parameter   LHU   = 6'b100101;           
    parameter   LB    = 6'b100000;
    parameter   LBU   = 6'b100100;
    parameter   SH    = 6'b101001;
    parameter   SB    = 6'b101000;
    parameter   LUI   = 6'b001111;               
    parameter   ORI   = 6'b001101;
    parameter   SLTI  = 6'b001010;
    parameter   SLTIU = 6'b001011;
    parameter   JAL   = 6'b000011;

    parameter   WORD_DATATYPE = 2'b00,HALF_DATATYPE=2'b01,BYTE_DATATYPE=2'b10;
    parameter   SIGN_DATA = 1'b1,UNSIGN_DATA = 1'b0;
    //OUTPUT
    parameter   RT_RegDst = 2'b01, RD_RegDst = 2'b00,RA_RegDst=2'b10;                           // RegDst
    parameter   BRANCHE = 2'b01,BRANCHN=2'b10, NOBRANCH = 2'b00;                 // Branch
    parameter   DMOUT_MemtoReg = 2'b01, ALURESULT_MemtoReg = 2'b00,PC_MemtoReg=2'b10;                 // MemtoReg
    parameter   RD2 = 1'b1, IMMEDIATE_NUMBER = 1'b0;            // AluSrc

    parameter   SL_ALUOP     = 4'b0000;
    parameter   BR_ALUOP     = 4'b0001;
    parameter   AL_ALUOP     = 4'b0010;
    parameter   LU_ALUOP     = 4'b0011;
    parameter   ADDI_ALUOP   = 4'b0100;
    parameter   ORI_ALUOP    = 4'b0101; // AlluOp 
    parameter   ANDI_ALUOP   = 4'b0110;
    parameter   XORI_ALUOP   = 4'b0111;
    parameter   SLTI_ALUOP   = 4'b1000;

    parameter   SLL   = 6'b000000;
    parameter   SRL   = 6'b000010;
    parameter   SRA   = 6'b000011;
    parameter   JR    = 6'b001000;

    parameter   MEMWRITE = 1'b1, NOMEMWRITE = 1'b0;             // MemWrite
    parameter   REGWRITE = 1'b1, NOREGWRITE = 1'b0;             // RegWrite
    parameter   JUMP = 2'b01,JR_JUMP=2'b10, NOJUMP = 2'b00;                     // Jump
    parameter   SIGN=1'b1,UNSIGN=1'b0;                          //extend

    reg   [19:0] controls;
    parameter   MEMREAD=1'b1,NOMEMREAD=1'b0;            
    assign {RegDst, Branch, MemtoReg, AluSrc, AluOp, MemWrite, RegWrite, Jump,Sign,DataType,DataSign,MemRead} = controls;

    always @(*)
    begin
       case(opcode)
            RTYPE:                                  // R type
            begin
                case(funct)
                SLL,SRL,SRA:
                controls <= {RD_RegDst, NOBRANCH, ALURESULT_MemtoReg,RD2, AL_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD};  
                JR:  controls <= {RT_RegDst, NOBRANCH, PC_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, NOREGWRITE, JR_JUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
                default :
                controls <= {RD_RegDst, NOBRANCH, ALURESULT_MemtoReg,RD2, AL_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD};     
                endcase  
            end
            ADDI : controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg,IMMEDIATE_NUMBER, ADDI_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            ADDIU: controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg,IMMEDIATE_NUMBER, ADDI_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            ANDI : controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg,IMMEDIATE_NUMBER, ANDI_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            ORI  : controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg,IMMEDIATE_NUMBER, ORI_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            XORI : controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg,IMMEDIATE_NUMBER, XORI_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            BEQ  : controls <= {RT_RegDst, BRANCHE, ALURESULT_MemtoReg, RD2, BR_ALUOP, NOMEMWRITE, NOREGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            J    : controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, NOREGWRITE, JUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            LW   : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,MEMREAD}; 
            SW   : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg,IMMEDIATE_NUMBER, SL_ALUOP, MEMWRITE, NOREGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            LUI  : controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg, IMMEDIATE_NUMBER, LU_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            SLTI : controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg, IMMEDIATE_NUMBER, SLTI_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            SLTIU: controls <= {RT_RegDst, NOBRANCH, ALURESULT_MemtoReg, IMMEDIATE_NUMBER, SLTI_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            BNE  : controls <= {RT_RegDst, BRANCHN, ALURESULT_MemtoReg, RD2, BR_ALUOP, NOMEMWRITE, NOREGWRITE, NOJUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD};
            LH   : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,HALF_DATATYPE,SIGN_DATA,MEMREAD}; 
            LHU  : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,HALF_DATATYPE,UNSIGN_DATA,MEMREAD};
            LB   : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,BYTE_DATATYPE,SIGN_DATA,MEMREAD}; 
            LBU  : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, REGWRITE, NOJUMP,SIGN,BYTE_DATATYPE,UNSIGN_DATA,MEMREAD}; 
            SH   : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, MEMWRITE, NOREGWRITE, NOJUMP,SIGN,HALF_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            SB   : controls <= {RT_RegDst, NOBRANCH, DMOUT_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, MEMWRITE, NOREGWRITE, NOJUMP,SIGN,BYTE_DATATYPE,SIGN_DATA,NOMEMREAD}; 
            JAL  : controls <= {RA_RegDst, NOBRANCH, PC_MemtoReg, IMMEDIATE_NUMBER, SL_ALUOP, NOMEMWRITE, REGWRITE, JUMP,SIGN,WORD_DATATYPE,SIGN_DATA,NOMEMREAD};
            default: controls <= 16'bxxxxxxxxx; 
       endcase
    end
       
endmodule